package com.tools.web.filter.cors;

import com.tools.common.io.CharsetEnum;
import com.tools.common.object.Note;

import java.util.Map;
import java.util.Objects;

/**
 * 跨域过滤器配置项包装类
 * */
@Note("跨域过滤器配置项包装类")
public class CorsSource {

    @Note("response 的 ContentType。默认为 JSON 字符串")
    private String responseContentType;

    @Note("response 的默认字符集。默认为 UTF-8")
    private CharsetEnum responseCharset;

    @Note("允许哪些域名能请求")
    private String allowOrigin;

    @Note("允许哪些请求方法。多个以逗号分隔")
    private String allowMethods;

    @Note("允许携带哪些请求头。多个以逗号分隔")
    private String allowHeaders;

    @Note("设置是否允许浏览器携带 Cookie 等标识")
    private boolean allowCredentials;

    @Note("设置预检请求的缓存结果有效时长，默认是 30 分钟（1800 秒）")
    private int maxAge;

    /* ********************************************************************************************
     *
     *         构造器
     *
     * *********************************************************************************************
     * */

    public CorsSource() {
        this.responseContentType = "application/json";
        this.responseCharset = CharsetEnum.UTF_8;
        this.allowOrigin = "*";
        this.allowMethods = "*";
        this.allowHeaders = "*";
        this.allowCredentials = true;
        this.maxAge = 1800;
    }

    public static CorsSource of() {
        return new CorsSource();
    }

    @Note("读取 properties 里的配置项，转为实例返回")
    public static CorsSource from(Map properties) {
        CorsSource source = new CorsSource();
        if(properties == null || properties.isEmpty()) return source;
        source.setResponseContentType((String) properties.get("cors-filter-responseContentType"));
        String charset = (String) properties.get("cors-filter-responseCharset");
        source.setResponseCharset(CharsetEnum.getEnumSafe(charset));
        source.setAllowOrigin((String) properties.get("cors-filter-allow-origin"));
        source.setAllowMethods((String) properties.get("cors-filter-allow-methods"));
        source.setAllowHeaders((String) properties.get("cors-filter-allow-headers"));
        source.setAllowCredentials((Boolean) properties.get("cors-filter-allow-credentials"));
        source.setMaxAge((Integer) properties.get("cors-filter-max-age"));
        return source;
    }

    /* ********************************************************************************************
     *
     *         Getter / Setter
     *
     * *********************************************************************************************
     * */

    public String getResponseContentType() {
        return responseContentType;
    }

    public void setResponseContentType(String responseContentType) {
        if(responseContentType != null && responseContentType.contains("/")) {
            this.responseContentType = responseContentType;
        }
    }

    public CharsetEnum getResponseCharset() {
        return responseCharset;
    }

    public void setResponseCharset(CharsetEnum responseCharset) {
        if(responseCharset != null) {
            this.responseCharset = responseCharset;
        }
    }

    public String getAllowOrigin() {
        return allowOrigin;
    }

    public void setAllowOrigin(String allowOrigin) {
        this.allowOrigin = (allowOrigin == null || !allowOrigin.isEmpty()) ? "*" : allowOrigin;
    }

    public String getAllowMethods() {
        return allowMethods;
    }

    public void setAllowMethods(String allowMethods) {
        this.allowMethods = (allowMethods == null || !allowMethods.isEmpty()) ? "*" : allowMethods;
    }

    public String getAllowHeaders() {
        return allowHeaders;
    }

    public void setAllowHeaders(String allowHeaders) {
        this.allowHeaders = (allowMethods == null || !allowMethods.isEmpty()) ? "*" : allowMethods;
    }

    public boolean isAllowCredentials() {
        return allowCredentials;
    }

    public void setAllowCredentials(Boolean allowCredentials) {
        this.allowCredentials = allowCredentials != null && allowCredentials;
    }

    public int getMaxAge() {
        return maxAge;
    }

    public void setMaxAge(Integer maxAge) {
        this.maxAge = (maxAge == null || maxAge < 1) ? 1800 : maxAge;
    }

    @Override
    public String toString() {
        return "CorsSource{" +
                "responseContentType=" + responseContentType +
                ", responseCharset=" + responseCharset +
                ", allowOrigin=" + allowOrigin +
                ", allowMethods=" + allowMethods +
                ", allowHeaders=" + allowHeaders +
                ", allowCredentials=" + allowCredentials +
                ", maxAge=" + maxAge +
                '}';
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        CorsSource that = (CorsSource) o;
        return Objects.equals(responseContentType, that.responseContentType) && responseCharset == that.responseCharset && allowCredentials == that.allowCredentials && maxAge == that.maxAge && Objects.equals(allowOrigin, that.allowOrigin) && Objects.equals(allowMethods, that.allowMethods) && Objects.equals(allowHeaders, that.allowHeaders);
    }

    @Override
    public int hashCode() {
        return Objects.hash(responseContentType, responseCharset, allowOrigin, allowMethods, allowHeaders, allowCredentials, maxAge);
    }

    /* ********************************************************************************************
     *
     *         链式调用
     *
     * *********************************************************************************************
     * */

    public CorsSource responseContentType(String responseContentType) {
        this.setResponseContentType(responseContentType);
        return this;
    }

    public CorsSource responseCharset(CharsetEnum responseCharset) {
        this.setResponseCharset(responseCharset);
        return this;
    }

    public CorsSource allowOrigin(String allowOrigin) {
        this.setAllowOrigin(allowOrigin);
        return this;
    }

    public CorsSource allowMethods(String allowMethods) {
        this.setAllowMethods(allowMethods);
        return this;
    }

    public CorsSource allowHeaders(String allowHeaders) {
        this.setAllowHeaders(allowHeaders);
        return this;
    }

    public CorsSource allowCredentials(Boolean allowCredentials) {
        this.setAllowCredentials(allowCredentials);
        return this;
    }

    public CorsSource maxAge(Integer maxAge) {
        this.setMaxAge(maxAge);
        return this;
    }
}
